package ccnu.agile.service;

import ccnu.agile.bean.request.Request;
import ccnu.agile.enums.EmsBusiness;
import ccnu.agile.utils.LogUtils;
import ccnu.agile.utils.RandUtils;
import ccnu.agile.utils.RedisUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.commons.lang.StringUtils;

/**
 * 验证码服务
 *
 * @author: JreamY
 */
public interface IVerifyCodeService {

    Integer DEFAULT_CODE_LEN = 6;

    /**
     * 发送验证码：业务使用
     *
     * @param request
     * @return
     */
    default VerifyResponse sendCode(Request request) {

        VerifyRequest verifyRequest = new VerifyRequest(request);
        RedisUtils.setString(redisKey(verifyRequest), verifyRequest.getVerifyCode(), 1800);

        return doSendCode(verifyRequest);
    }

    /**
     * 发送验证码：核心重写
     *
     * @param request
     */
    VerifyResponse doSendCode(VerifyRequest request);

    /**
     * 验证码校验：业务使用
     *
     * @param request
     * @return
     */
    default VerifyResponse verifyCode(Request request) {
        return doVerifyCode(new VerifyRequest(request));
    }

    /**
     * 验证码校验：核心重写
     *
     * @param request
     * @return
     */
    default VerifyResponse doVerifyCode(VerifyRequest request) {

        String realCode = RedisUtils.getString(redisKey(request));
        LogUtils.info(this, "realCode = {}, verifyCode = {}", realCode, request.getVerifyCode());

        if (StringUtils.isEmpty(realCode)) {
            return VerifyResponse.codeExpire();
        }

        if (realCode.equals(request.getVerifyCode())) {
            return VerifyResponse.codeError();
        }

        return VerifyResponse.success();
    }

    /**
     * redis缓存key
     *
     * @param request
     * @return
     */
    String redisKey(VerifyRequest request);

    /**
     * 6位验证码生成
     *
     * @return
     */
    default String generateCode() {
        return RandUtils.randStr(DEFAULT_CODE_LEN, true);
    }

    @Data
    class VerifyRequest {

        /**
         * 业务类型
         */
        EmsBusiness emsBusiness;

        /**
         * 验证码接收者
         */
        String receiver;

        /**
         * 验证码
         */
        String verifyCode;

        public VerifyRequest(Request request) {

            this.emsBusiness = request.getEmsBusiness();
            this.receiver = (String) request.get("receiver");
            this.verifyCode = (String) request.get("verifyCode");
        }
    }

    @Data
    @AllArgsConstructor
    class VerifyResponse {

        /**
         * 校验成功
         */
        final static int SUCCESS = 0;
        /**
         * 验证码错误
         */
        final static int CODE_ERROR = 101;
        /**
         * 验证码已失效
         */
        final static int CODE_EXPIRE = 102;

        int retCode;

        public static VerifyResponse success() {
            return new VerifyResponse(SUCCESS);
        }

        public static VerifyResponse codeError() {
            return new VerifyResponse(CODE_ERROR);
        }

        public static VerifyResponse codeExpire() {
            return new VerifyResponse(CODE_EXPIRE);
        }

        public boolean isSuccess() {
            return this.retCode == SUCCESS;
        }

        public boolean isCodeError() {
            return this.retCode == CODE_ERROR;
        }

        public boolean isCodeExpire() {
            return this.retCode == CODE_EXPIRE;
        }
    }

}
